package linker

import (
	"bytes"
	"debug/elf"
	"risc-v/ld/pkg/utils"
)

type FileType = uint8

const (
	FileTypeUnknown FileType = iota //未知文件类型
	FileTypeEmpty   FileType = iota // 文件为空
	FileTypeObject  FileType = iota // ELF( ObjectFile )文件(.o 后缀)
	FileTypeArchive FileType = iota // 静态库文件 (.a 后缀)
)

// GetFileType 从 ELF 文件中读取文件类型
// 即，判断 FileHeader.Type 的类型
func GetFileType(content []byte) FileType {
	if len(content) == 0 {
		return FileTypeEmpty
	}

	if CheckMagic(content) {
		e := elf.Type(utils.Read[uint16](content[16:]))
		switch e {
		case elf.ET_REL:
			return FileTypeObject
		case elf.ET_EXEC:
			utils.Fatal("this is a executable file")
		case elf.ET_DYN:
			utils.Fatal("this is a dynamic library")
		}
		return FileTypeUnknown
	}

	// 静态库文件
	// https://en.wikipedia.org/wiki/Ar_(Unix)
	if bytes.HasPrefix(content, []byte{'!', '<', 'a', 'r', 'c', 'h', '>', '\n'}) {
		return FileTypeArchive
	}

	return FileTypeUnknown
}

// CheckFileCompatibility 检查 ObjectFile 机器类型是否和 ContextArgs 中的一致
func CheckFileCompatibility(ctx *Context, file *File) {
	machineType := GetMachineTypeFromContent(file.Content)
	if machineType != ctx.Args.Emulation {
		utils.Fatal("incompatible file type")
	}
}
